import type { MaybeRefOrGetter } from 'vue';
import { makeDestructurable, useElementSize } from '@peng_kai/kit/libs/vueuse';
import type { Simplify } from 'type-fest';

type PadPrefix<T extends string> = T | `lt${T}`;
export type TPresetBreakpoints = Record<PadPrefix<keyof typeof presetBreakpoints>, boolean>;

/**
 * 参考 tailwindcss-container-queries 插件的断点配置
 * @link https://github.com/tailwindlabs/tailwindcss-container-queries?tab=readme-ov-file#configuration
 */
const presetBreakpoints = {
  'xs': 320,
  'sm': 384,
  'md': 448,
  'lg': 512,
  'xl': 576,
  '2xl': 672,
  '3xl': 768,
  '4xl': 896,
  '5xl': 1024,
  '6xl': 1152,
  '7xl': 1280,
};

export function useElementBreakpoint<B extends Record<string, number>>(
  breakpoints: MaybeRefOrGetter<B> = {} as B,
  options?: { box?: 'content-box' | 'border-box' },
) {
  const eleRef = ref<HTMLElement | null>(null);
  const { width } = useElementSize(eleRef, undefined, { box: options?.box });
  const bpEntries = computed(() => Object.entries(toValue(breakpoints)).sort((a, b) => a[1] - b[1]));
  const presetEntries = Object.entries(presetBreakpoints).sort((a, b) => a[1] - b[1]);
  const eleBp = computed(() => ({
    // 自定义断点
    ...Object.fromEntries(bpEntries.value.map(([key, value]) => [key, width.value >= value])),
    ...Object.fromEntries(bpEntries.value.map(([key, value]) => [`lt${key}`, width.value < value])),
    // 预设断点
    ...Object.fromEntries(presetEntries.map(([key, value]) => [key, width.value >= value])),
    ...Object.fromEntries(presetEntries.map(([key, value]) => [`lt${key}`, width.value < value])),
  } as Simplify<Record<PadPrefix<keyof (B & typeof presetBreakpoints) & string>, boolean>>));

  const setEle = (ele: any) => {
    eleRef.value = ele instanceof HTMLElement ? ele : (ele?.$el ?? null);
  };

  return makeDestructurable(
    { setEle, eleBp, width } as const,
    [setEle, eleBp, width] as const,
  );
}
